using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using Microsoft.WowAddonStudio.FrameXml.Components.Layout;

namespace Microsoft.WowAddonStudio.FrameXml.Components.Editors
{
	/// <summary>
	/// 
	/// </summary>
	public class ControlSelectorUI : ListBox
	{
		private readonly IServiceProvider provider;
		private bool showAll;

		public ControlSelectorUI(IServiceProvider provider, bool showAll, Control instance)
			: this(provider, showAll, new List<Control>() { instance })
		{

		}

		/// <summary>
		/// Initializes a new instance of the <see cref="ControlSelectorUI"/> class.
		/// </summary>
		/// <param name="provider">The provider.</param>
		/// <param name="showAll">if set to <c>true</c> [show all].</param>
		/// <param name="instance">The instance.</param>
		public ControlSelectorUI(IServiceProvider provider, bool showAll, IList<Control> instance)
		{
			this.provider = provider;
			this.showAll = showAll;
			this.InstanceList = instance;

			InitializeComponent();

			FillControls();
		}


		/// <summary>
		/// Gets the service.
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="serviceType">Type of the service.</param>
		/// <returns></returns>
		protected T GetService<T>(Type serviceType)
		{
			return (T) provider.GetService(serviceType);
		}

		/// <summary>
		/// Fills the controls.
		/// </summary>
		protected virtual void FillControls()
		{
			var service = (IDesignerHost) provider.GetService(typeof (IDesignerHost));
			if (service != null)
			{
				try
				{
					BeginUpdate();
					Items.Clear();
					Items.Add(String.Empty);
					AddControls(service.RootComponent as Control);
				}
				finally
				{
					Sorted = true;
					EndUpdate();
				}
			}
		}

		/// <summary>
		/// Inits the controls.
		/// </summary>
		/// <param name="component">The component.</param>
		protected virtual void AddControls(Control component)
		{
			if (component == null) return;

            if ((component is LayoutFrameControl || ShowAll) && !InstanceList.Contains(component))
            {
                if (((LayoutFrameControl) component).LayoutEngine.CanAddDependency(InstanceList[0].Name, component.Name))
                    Items.Add(component.Name);
            }

		    if (component.Controls.Count > 0)
			{
				foreach (Control control in component.Controls)
					AddControls(control);
			}
		}

		/// <summary>
		/// Gets or sets a value indicating whether [show all].
		/// </summary>
		/// <value><c>true</c> if [show all]; otherwise, <c>false</c>.</value>
		public bool ShowAll
		{
			get { return showAll; }
			set
			{
				showAll = value;
				FillControls();
			}
		}

		/// <summary>
		/// Gets or sets the value.
		/// </summary>
		/// <value>The value.</value>
		public virtual string Value{ get; set;}

		/// <summary>
		/// Gets or sets the instance list.
		/// </summary>
		/// <value>The instance list.</value>
		protected IList<Control> InstanceList { get; set; }

		/// <summary>
		/// Initializes the component.
		/// </summary>
		protected virtual void InitializeComponent()
		{
			BorderStyle = BorderStyle.None;
			SelectionMode = SelectionMode.One;
			SelectedIndexChanged += UISelectedIndexChanged;
		}

		/// <summary>
		/// UIs the selected index changed.
		/// </summary>
		/// <param name="sender">The sender.</param>
		/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
		private void UISelectedIndexChanged(object sender, EventArgs e)
		{
			UISelectedIndexChanged(e);
		}

		/// <summary>
		/// UIs the selected index changed.
		/// </summary>
		/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
		protected virtual void UISelectedIndexChanged(EventArgs e)
		{
			Value = (string)SelectedItem;

			var editorService = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
			if (editorService != null)
			{
				editorService.CloseDropDown();
			}
		}
	}
}